#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "projectinfoimport.h"
#include "typeimport.h"
#include "constantimport.h"
#include "operatorimporter.h"
#include <QFileDialog>
#include <QFileInfo>
#include <QMessageBox>
#include <QRegExp>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setFixedSize(600,375);//设置窗口固定大小
}

MainWindow::~MainWindow()
{
    delete ui;
}

//增加int_signal、bool_signal、device_signal、real_signal四种数据类型
void addSignalTypes(DataTypeDefine::DataTypeList &datas)
{
    //int_signal
    DataTypeDefine::DataType int_signal;
    int_signal.name="int_signal";
    int_signal.isArray=false;
    int_signal.isStructure=true;
    int_signal.definition="<structure>";
    int_signal.oid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    //value
    DataTypeDefine::StructEle value;
    value.elementName="Value";
    value.elementDef="int";
    value.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    value.structId=int_signal.oid;
    int_signal.structElements.append(value);
    //status
    DataTypeDefine::StructEle status;
    status.elementName="Status";
    status.elementDef="bool";
    status.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    status.structId=int_signal.oid;
    int_signal.structElements.append(status);
    //pad1
    DataTypeDefine::StructEle pad1;
    pad1.elementName="pad1";
    pad1.elementDef="bool";
    pad1.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    pad1.structId=int_signal.oid;
    int_signal.structElements.append(pad1);

    datas.append(int_signal);

    //bool_signal
    DataTypeDefine::DataType bool_signal;
    bool_signal.name="bool_signal";
    bool_signal.isArray=false;
    bool_signal.isStructure=true;
    bool_signal.definition="<structure>";
    bool_signal.oid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    //value
    DataTypeDefine::StructEle value1;
    value1.elementName="Value";
    value1.elementDef="bool";
    value1.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    value1.structId=bool_signal.oid;
    bool_signal.structElements.append(value1);
    //status
    DataTypeDefine::StructEle status1;
    status1.elementName="Status";
    status1.elementDef="bool";
    status1.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    status1.structId=bool_signal.oid;
    bool_signal.structElements.append(status1);

    datas.append(bool_signal);

    //device_signal
    DataTypeDefine::DataType device_signal;
    device_signal.name="device_signal";
    device_signal.isArray=false;
    device_signal.isStructure=true;
    device_signal.definition="<structure>";
    device_signal.oid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    //msgCod1
    DataTypeDefine::StructEle msgCod1;
    msgCod1.elementName="msgCod1";
    msgCod1.elementDef="int";
    msgCod1.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    msgCod1.structId=device_signal.oid;
    device_signal.structElements.append(msgCod1);
    //msgCod2
    DataTypeDefine::StructEle msgCod2;
    msgCod2.elementName="msgCod2";
    msgCod2.elementDef="int";
    msgCod2.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    msgCod2.structId=device_signal.oid;
    device_signal.structElements.append(msgCod2);

    datas.append(device_signal);

    //real_signal
    DataTypeDefine::DataType real_signal;
    real_signal.name="real_signal";
    real_signal.isArray=false;
    real_signal.isStructure=true;
    real_signal.definition="<structure>";
    real_signal.oid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    //Value
    DataTypeDefine::StructEle value2;
    value2.elementName="Value";
    value2.elementDef="real";
    value2.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    value2.structId=real_signal.oid;
    real_signal.structElements.append(value2);

    //status
    DataTypeDefine::StructEle status2;
    status2.elementName="Status";
    status2.elementDef="bool";
    status2.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    status2.structId=real_signal.oid;
    real_signal.structElements.append(status2);

    //pad1
    DataTypeDefine::StructEle pad11;
    pad11.elementName="pad1";
    pad11.elementDef="bool";
    pad11.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    pad11.structId=real_signal.oid;
    real_signal.structElements.append(pad11);

    //pad2
    DataTypeDefine::StructEle pad12;
    pad12.elementName="pad2";
    pad12.elementDef="bool";
    pad12.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    pad12.structId=real_signal.oid;
    real_signal.structElements.append(pad12);

    //pad3
    DataTypeDefine::StructEle pad13;
    pad13.elementName="pad3";
    pad13.elementDef="bool";
    pad13.elementOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
    pad13.structId=real_signal.oid;
    real_signal.structElements.append(pad13);

    datas.append(real_signal);

}

//处理默认模型文件中的'\x00'，改为'/x00'
void x00_Process(QString redaceProjectPath,QString scadeProjectName)
{
    QFile constantFile(redaceProjectPath+"/"+scadeProjectName+"/Constant.xml");

    QString strAll;
    QStringList strList;

    if(constantFile.open(QIODevice::ReadOnly|QIODevice::Text))
    {
        QTextStream stream(&constantFile);
        stream.setCodec("UTF-8");
        strAll=stream.readAll();
    }

    constantFile.close();

    if(constantFile.open(QIODevice::WriteOnly|QIODevice::Text))
    {
        QTextStream stream(&constantFile);
        stream.setCodec("utf-8");
        strList=strAll.split("\n");

        for(int i=0;i<strList.size();i++)
        {
            if(strList.at(i).contains("<ConstValue value=\"'\\x00'\"/>"))
            {
                QString str=strList.at(i);
                strList[i]=str.replace("<ConstValue value=\"'\\x00'\"/>","<ConstValue value=\"'/x00'\"/>");
            }
            stream<<strList.at(i)<<endl;
        }

    }

    constantFile.close();
}

void generateEmptyConstantFile(const QString& filePath)
{
    QFile file(filePath);

    //默认模型文件不存在时
    if (!file.open(QFile::ReadOnly| QFile::Text))
    {
        if (!file.open(QFile::WriteOnly| QFile::Text|QFile::Truncate))
        {
            return;
        }

        QDomDocument doc;

        QDomProcessingInstruction instruction;

        instruction = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");
        doc.appendChild(instruction);

        QDomElement root = doc.documentElement();
        if(root.isNull())
        {
            root = doc.createElement("File");
            root.setAttribute("Type","Constant");

            QDomElement declarations = doc.createElement("declarations");

            root.appendChild(declarations);
        }

        doc.appendChild(root);

        QTextStream stream( &file );
        stream.setCodec("utf-8");
        doc.save(stream,2,QDomNode::EncodingFromTextStream);

        file.close();
    }
}

//导入前检查，检查导入的SCADE工程和生成文件夹合法性
bool MainWindow::checkBeforeImporte(const QString& scadeProjectFilePath,const QString& scadeProjectName,const QString& redaceProjectPath)
{
    if(scadeProjectFilePath.isEmpty())
    {
        QMessageBox::information(this,"提示信息","SCADE工程文件路径为空！");
        return false;
    }

    if(!QFile().exists(scadeProjectFilePath))
    {
        QMessageBox::information(this,"提示信息","SCADE工程文件不存在！");
        return false;
    }

    if(!scadeProjectFilePath.endsWith(".etp"))
    {
        QMessageBox::information(this,"提示信息","SCADE工程文件不是.etp文件！");
        return false;
    }

    //检查SCADE工程名是否符合REDACE命名约束
    QRegExp rx;
    rx.setPatternSyntax(QRegExp::RegExp);
    rx.setCaseSensitivity(Qt::CaseSensitive); //大小写敏感
    rx.setPattern(QString("[_a-zA-Z][_a-zA-Z0-9]*"));
    if(!rx.exactMatch(scadeProjectName))
    {
        QMessageBox::information(this,"提示信息","SCADE工程名必须由下划线、字母和数字组成，且不能以数字开头！");
        return false;
    }

    QStringList keyWords;
    keyWords<<"int_signal"<<"bool_signal"<<"device_signal"<<"real_signal"<<"_L"<<"acg_"<<"_null"<<"null"<<"_"<<"debug"<<"user_macros"<<"opeOffset"<<"typeOffset"<<"mainC"<<"USERHEADER"<<"ST_t"<<"UI_t"<<"FL_t"<<"BO_t"<<"msgCod_t"<<"TRUE"<<"FALSE"<<"TEST_MODE"<<"NORMAL_MODE"<<"OP_CLEAR_FORCELIST"<<"MAX_FORCE_COUNT"<<"Global_STR"<<"forcelist_t"<<"AssignCondition_STR"<<"debug_init"<<"SYS_GV"<<"Good"<<"Bad";
    keyWords<<"abstract"<<"activate"<<"and"<<"auto"<<"assume"<<"automaton"<<"bool"<<"break"<<"case"<<"char"<<"clock"<<"const"<<"continue"<<"default"<<"div"<<"do"<<"double"<<"else"<<"elsif"<<"emit"<<"end"<<"enum"<<"extern"<<"every"<<"false"<<"fby"<<"flatten"<<"fold"<<"foldi"<<"foldw"<<"foldwi"<<"function"<<"for"<<"funcation"<<"float"<<"guarantee"<<"group"<<"goto"<<"if"<<"imported"<<"initial"<<"inline"<<"int"<<"is"<<"last"<<"let"<<"long"<<"make"<<"map"<<"mapfold"<<"mapi"<<"mapw"<<"mapwi"<<"match"<<"merge"<<"mod"<<"node"<<"not"<<"numeric"<<"of"<<"onreset"<<"open"<<"or"<<"package"<<"parameter"<<"pre"<<"private"<<"public"<<"real"<<"restart"<<"restrict"<<"resume"<<"returns"<<"reverse"<<"return"<<"sensor"<<"short"<<"sig"<<"signed"<<"sizeof"<<"specialize"<<"state"<<"static"<<"struct"<<"switch"<<"synchro"<<"tel"<<"then"<<"times"<<"transpose"<<"true"<<"type"<<"typedef"<<"unless"<<"until"<<"union"<<"unsigned"<<"var"<<"void"<<"volatile"<<"when"<<"where"<<"with"<<"while"<<"xor"<<"_Bool"<<"_Complex"<<"_Imaginary";
    if(keyWords.contains(scadeProjectName)||scadeProjectName.startsWith("acg_",Qt::CaseSensitive))
    {
        QMessageBox::information(this,"提示信息","SCADE工程名为关键字，名称非法！");
        return false;
    }

    if(redaceProjectPath.isEmpty())
    {
        QMessageBox::information(this,"提示信息","MODEN工程路径为空！");
        return false;
    }

    if(!QDir().exists(redaceProjectPath))
    {
        QMessageBox::information(this,"提示信息","MODEN工程路径不存在！");
        return false;
    }

    for(int i=0;i<redaceProjectPath.size();i++)
    {
        if(redaceProjectPath.at(i).unicode()>= 0x4E00&&redaceProjectPath.at(i).unicode()<= 0x9FA5)
        {
            QMessageBox::information(this,"提示信息","MODEN工程路径存在中文字符！请更换路径");
            return false;
        }
    }


    QString dirName=redaceProjectPath+"/"+scadeProjectName;//REDACE工程文件夹
    QDir dir(dirName);

    if(!dir.exists())
    {
        dir.mkdir(dirName);//创建文件夹
    }
    else
    {
        QMessageBox::information(this,"提示信息","MODEN工程路径下存在同名文件夹，请选择其它路径");
        return false;
        //        dir.removeRecursively();//如果生成的REDACE工程路径下，存在同名文件夹，删除文件夹中的所有文件
        //        dir.mkdir(dirName);
    }

    return true;
}

//实例化泛型
void instantiateGenerics(QList<opcallOperator> opCallList,QList<OperatorData> operatorList,QString redaceProjectPath,QString scadeProjectName)
{
    int genericsNumber=0;//实例化泛型时，避免重名

    //获取所有含泛型操作符被调用的列表
    for(int i=0;i<opCallList.size();i++)
    {
        genericsNumber++;
        opcallOperator opcall=opCallList.at(i);
        OperatorData opcallData;//被调用的操作符的数据
        OperatorData operatorData;//操作符数据

        QString callName = opcall.opcallName;
        if(callName.contains("::")){
            QStringList l = callName.split("::");
            callName = l.at(1);
        }
        for(int n=0;n<operatorList.size();n++)
        {
            if(callName==operatorList.at(n).operatorName)
            {
                opcallData=operatorList.at(n);
            }

            if(opcall.operatorName==operatorList.at(n).operatorName)
            {
                operatorData=operatorList.at(n);
            }
        }

        if(opcallData.hasT==true)
        {
            opcallData.isNew=true;
            opcallData.hasT=false;
            opcallData.operatorName=opcallData.operatorName+"_"+operatorData.operatorName+"_"+QString("%1").arg(genericsNumber);
            opcallData.operatorFileName=opcallData.operatorName+".redace";
            opcallData.path=opcallData.path+"_"+operatorData.operatorName;

            QList<QDomNode> TNodeList;//泛型实例化时的节点

            Equation equation=opcall.equation;
            QStringList dataTypeList;

            //输入变量
            if(equation.operatorType=="OpCall")
            {
                for(int k=0;k<equation.opCall.calls.size();k++)
                {
                    QString localName=equation.opCall.calls.at(k);

                    for(int j=0;j<operatorData.variables.size();j++)
                    {
                        Variable var=operatorData.variables.at(j);

                        if(var.name==localName)
                        {
                            dataTypeList<<var.dataType;
                            TNodeList.append(var.node.firstChild().cloneNode(true));
                        }
                    }
                }
            }

            if(equation.operatorType=="IteratorOp")
            {
                for(int m=0;m<equation.iteratorOp.calls.size();m++)
                {
                    QString localName=equation.iteratorOp.calls.at(m);

                    for(int j=0;j<operatorData.variables.size();j++)
                    {
                        Variable var=operatorData.variables.at(j);

                        if(var.name==localName)
                        {
                            TNodeList.append(var.node.firstChild().firstChild().firstChild().cloneNode(true));
                        }
                    }
                }
            }

            if(equation.operatorType=="PartialIteratorOp")
            {
                for(int k=0;k<equation.partialIteratorOp.calls.size();k++)
                {
                    QString localName=equation.partialIteratorOp.calls.at(k);

                    for(int j=0;j<operatorData.variables.size();j++)
                    {
                        Variable var=operatorData.variables.at(j);

                        if(var.name==localName)
                        {
                            TNodeList.append(var.node.firstChild().firstChild().firstChild().cloneNode(true));
                        }
                    }
                }
            }


            //输出变量
            for(int k=0;k<equation.lefts.size();k++)
            {
                QString localName=equation.lefts.at(k);

                for(int j=0;j<operatorData.variables.size();j++)
                {
                    Variable var=operatorData.variables.at(j);

                    if(var.name==localName)
                    {
                        if(equation.operatorType=="OpCall")
                        {
                            TNodeList.append(var.node.firstChild().cloneNode(true));
                        }

                        if(equation.operatorType=="IteratorOp"||equation.operatorType=="PartialIteratorOp")
                        {
                            TNodeList.append(var.node.firstChild().firstChild().firstChild().cloneNode(true));
                        }

                    }
                }
            }

            for(int k=0;k<TNodeList.size();k++)
            {
                Variable var=opcallData.variables.at(k);
                var.node.replaceChild(TNodeList.at(k).cloneNode(true),var.node.firstChild());
            }

            //修改local变量
            for(int k=0;k<opcallData.equations.size();k++)
            {
                Equation equation=opcallData.equations.at(k);

                //input引入的local变量
                if(equation.type=="inputVar")
                {
                    Variable inputVar;
                    Variable localVar;

                    for(int j=0;j<opcallData.variables.size();j++)
                    {
                        Variable var=opcallData.variables.at(j);
                        if(var.name==equation.rightVarRef){
                            inputVar=var;
                        }

                        if(var.name==equation.lefts.at(0)){
                            localVar=var;
                        }
                    }

                    localVar.node.replaceChild(inputVar.node.firstChild().cloneNode(true),localVar.node.firstChild());
                }

                //操作符引入的local变量(只能自动修改直接连接output的local变量)
                if(equation.type=="outputVar")
                {
                    Variable outputVar;
                    Variable localVar;

                    for(int j=0;j<opcallData.variables.size();j++)
                    {
                        Variable var=opcallData.variables.at(j);
                        if(var.name==equation.lefts.at(0)){
                            outputVar=var;
                        }

                        if(var.name==equation.rightVarRef)
                            localVar=var;
                    }

                    localVar.node.replaceChild(outputVar.node.firstChild().cloneNode(true),localVar.node.firstChild());
                }

                //结构体的元素引入的local变量
                if(equation.type=="immediate")
                {
                    Variable localVar;

                    for(int j=0;j<opcallData.variables.size();j++)
                    {
                        Variable var=opcallData.variables.at(j);

                        if(var.name==equation.lefts.at(0))
                            localVar=var;
                    }

                    QDomNode typeNode;

                    if(localVar.hasT==true)
                    {
                        QStringList strList=equation.text.split(".");
                        if(strList.size() >1){
                            QString structVarName=strList.at(0);
                            QString fieldName=strList.at(1);

                            for(int t=0;t<opcallData.variables.size();t++)
                            {
                                Variable var=opcallData.variables.at(t);

                                if(' '+var.name==structVarName&&var.isStruct==true)
                                {
                                    QDomNode node=var.node.cloneNode(true);

                                    QDomNode fieldsNode=node.firstChild().firstChild().firstChild();
                                    QDomNodeList nodeList=fieldsNode.childNodes();

                                    for(int n=0;n<nodeList.size();n++)
                                    {
                                        QDomNode node=nodeList.at(n);

                                        if(node.toElement().attribute("name")+" "==fieldName)
                                        {
                                            typeNode=node.firstChild().cloneNode(true);
                                        }
                                    }
                                }
                            }

                            localVar.node.replaceChild(typeNode.cloneNode(true),localVar.node.firstChild());
                        }
                    }
                }
            }

            //修改实例化操作符的变量、dia的oid，保持oid的唯一性
            for(auto &item:opcallData.variables)
            {
                item.id=QUuid::createUuid().toString(QUuid::WithoutBraces);
                item.node.namedItem("oid").toElement().setAttribute("value",item.id);
            }

            for(auto &item:opcallData.diagrams)
            {
                QString newDiaOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
                item.redaceOid=newDiaOid;

            }

            OperatorImporter operatorImporter;
            operatorImporter.m_operator=opcallData;
            operatorImporter.saveOperatorFile(redaceProjectPath,scadeProjectName,operatorImporter.m_operator.operatorFileName,operatorImporter.m_operator);
            operatorImporter.saveDiagramFile(redaceProjectPath+"/"+scadeProjectName,operatorImporter.m_operator);

            //修改rpf文件
            QFile file(redaceProjectPath+"/"+scadeProjectName+"/"+scadeProjectName+".rpf");

            QString strAll;
            QStringList strList;

            if(file.open(QIODevice::ReadOnly|QIODevice::Text))
            {
                QTextStream stream(&file);
                stream.setCodec("UTF-8");
                strAll=stream.readAll();
            }

            file.close();

            if(file.open(QIODevice::WriteOnly|QIODevice::Text))
            {
                QTextStream stream(&file);
                stream.setCodec("utf-8");
                strList=strAll.split("\n");

                for(int y=0;y<strList.size();y++)
                {
                    stream<<strList.at(y)<<endl;

                    if(strList.at(y).contains("foldertype=\"operator\""))
                    {
                        stream<<"      <FileRef id=\"0\" CRC=\"\" Name=\""+opcallData.operatorName+"\" Path=\".\\"+opcallData.operatorFileName+"\"/>"<<endl;
                    }
                }
            }

            //修改生成后的redace文件, 替换未被实例化的泛型
            if(dataTypeList.size() > 0){
                QFile opfile(redaceProjectPath+"/"+scadeProjectName+"/"+opcallData.operatorFileName);
                qDebug()<<"afile:"<<redaceProjectPath+"/"+scadeProjectName+"/"+opcallData.operatorFileName;
                QString filecontent;
                QStringList lines;

                if(opfile.open(QIODevice::ReadOnly|QIODevice::Text))
                {
                    QTextStream stream(&opfile);
                    stream.setCodec("UTF-8");
                    filecontent=stream.readAll();
                }

                opfile.close();

                if(opfile.open(QIODevice::WriteOnly|QIODevice::Text))
                {
                    QTextStream stream(&opfile);
                    stream.setCodec("utf-8");
                    lines=filecontent.split("\n");

                    for(int y=0;y<lines.size();y++)
                    {
                        if(lines.at(y).contains("'T"))
                        {
                            lines[y].replace("'T", dataTypeList.at(0));
                        }

                        stream<<lines.at(y)<<endl;
                    }
                }

            }

            //修改调用该含泛型操作符的操作符的文件
            QFile file1(redaceProjectPath+"/"+scadeProjectName+"/"+operatorData.operatorFileName);

            QString strAll1;
            QStringList strList1;

            if(file1.open(QIODevice::ReadOnly|QIODevice::Text))
            {
                QTextStream stream(&file1);
                stream.setCodec("UTF-8");
                strAll1=stream.readAll();
            }

            file1.close();

            if(file1.open(QIODevice::WriteOnly|QIODevice::Text))
            {
                QTextStream stream(&file1);
                stream.setCodec("utf-8");
                strList1=strAll1.split("\n");

                bool index=false;//标志位，控制只修改一处。为了适配多次调用相同的含泛型操作符

                for(int i=0;i<strList1.size();i++)
                {
                    if(strList1.at(i).contains("<OperatorRef name=\""+callName+"\"/>")&&index==false)
                    {
                        index=true;
                        strList1[i].replace("<OperatorRef name=\""+callName+"\"/>","<OperatorRef name=\""+opcallData.operatorName+"\"/>");
                    }

                    stream<<strList1.at(i)<<endl;
                }
            }

            //修改页面文件
            for(int i=0;i<operatorData.diagrams.size();i++)
            {
                QFile file(redaceProjectPath+"/"+scadeProjectName+"/"+"POUs"+"/"+operatorData.operatorName+"/"+operatorData.diagrams.at(i).name);

                QString strAll;
                QStringList strList;

                if(file.open(QIODevice::ReadOnly|QIODevice::Text))
                {
                    QTextStream stream(&file);
                    stream.setCodec("UTF-8");
                    strAll=stream.readAll();
                }

                file.close();

                if(file.open(QIODevice::WriteOnly|QIODevice::Text))
                {
                    QTextStream stream(&file);
                    stream.setCodec("utf-8");
                    strList=strAll.split("</EquationGE>");

                    bool index=false;//标志位，控制只修改一处。为了适配多次调用相同的含泛型操作符

                    for(int i=0;i<strList.size();i++)
                    {
                        //普通泛型操作符
                        if(strList.at(i).contains("OpeName=\""+callName+"\"")&&index==false)
                        {
                            index=true;
                            strList[i].replace("OpeName=\""+callName+"\"","OpeName=\""+opcallData.operatorName+"\"");
                        }

                        //泛型操作符的高阶
                        if(strList.at(i).contains("UsedIdName=\""+callName+"\" RefName=\""+callName+"\"")&&index==false)
                        {
                            index=true;
                            strList[i].replace("UsedIdName=\""+callName+"\" RefName=\""+callName+"\"","UsedIdName=\""+opcallData.operatorName+"\" RefName=\""+opcallData.operatorName+"\"");
                        }

                        if(i!=strList.size()-1)
                        {
                            stream<<strList.at(i)+"</EquationGE>";
                        }
                        else
                        {
                            stream<<strList.at(i);
                        }
                    }
                }
            }


        }

    }
}

//实例化参数
void instantiateParameter(QList<opcallParaOperator> &paraOperatorList,QList<OperatorData> &operatorList,QString redaceProjectPath,QString scadeProjectName)
{
    opcallParaOperator opcall;
    OperatorData data;

    QDomDocument document;
    qDebug()<<"instantiateParameter："<<paraOperatorList.size();
    for(int i=0;i<paraOperatorList.size();i++)
    {
        opcall=paraOperatorList.at(i);
        QString opName = opcall.operatorName;
        if(opName.contains("::")){
            QStringList l = opName.split("::");
            opName = l.at(1);
        }
        qDebug()<<"opName:"<<opName;

        for(int n=0;n<operatorList.size();n++)
        {

            qDebug()<<"operatorList.at(n).operatorName:"<<operatorList.at(n).operatorName;
            if(opName==operatorList.at(n).operatorName)
            {
                qDebug()<<__FILE__<<":"<<__LINE__<<":"<<opName;
                data=operatorList.at(n);
            }
        }

        data.isNew=true;
        data.hasPara=false;
        data.operatorName=data.operatorName+"_"+opcall.paraValue.value;
        data.operatorFileName=data.operatorName+".redace";
        data.parameter.clear();
        data.path=data.path+"_"+opcall.paraValue.value;

        //实例化变量
        QDomNode node=opcall.paraValue.node.cloneNode(true);

        for(int i=0;i<data.variables.size();i++)
        {
            Variable var;
            var=data.variables.at(i);

            QDomNodeList nodeList=var.node.childNodes();

            QDomElement varEle;
            if(var.hasPara==true)
            {
                var.hasPara=false;

                varEle=document.createElement("Variable");
                varEle.setAttribute("name",var.name);

                QDomElement typeEle=document.createElement("type");
                varEle.appendChild(typeEle);
                QDomElement tableEle=document.createElement("Table");
                typeEle.appendChild(tableEle);
                tableEle.appendChild(var.node.firstChild().firstChild().firstChild().cloneNode(true));
                QDomElement sizeEle=document.createElement("size");
                sizeEle.appendChild(node.cloneNode(true));
                tableEle.appendChild(sizeEle);

                for(int i=1;i<nodeList.size();i++)
                {
                    if(nodeList.at(i).toElement().tagName()=="oid")
                    {
                        nodeList.at(i).toElement().setAttribute("value",QUuid::createUuid().toString(QUuid::WithoutBraces));
                    }
                    varEle.appendChild(nodeList.at(i).cloneNode(true));
                }

                var.node=varEle;

                data.variables[i]=var;

            }
        }

        //Equation实例化
        for(int i=0;i<data.equations.size();i++)
        {
            Equation equation=data.equations.at(i);
            QDomNode equationNode=data.equations.at(i).node.cloneNode(true);
            QDomNode rightNode=equationNode.childNodes().at(1);

            if(equation.isParaHigh==true&&equation.type=="constant")
            {
                equation.isParaHigh=false;
                equation.type="immediate";
                equation.text=opcall.paraValue.value;
                rightNode.replaceChild(node.cloneNode(true),rightNode.firstChild());

                //修改页面文件
                for(int i=0;i<data.diagrams.size();i++)
                {
                    Diagram dia=data.diagrams.at(i);

                    for(int i=0;i<dia.equations.size();i++)
                    {
                        Equation equation=dia.equations.at(i);

                        if(equation.isParaHigh&&equation.type=="constant")
                        {
                            equation.eleType="ELETYPE_IMMEDIATE";
                            equation.text=opcall.paraValue.value;

                            dia.equations[i]=equation;
                        }
                    }

                    data.diagrams[i]=dia;
                }
            }

            if(equation.isParaHigh==true&&equation.type=="operator")
            {
                QDomNode opcallNode=rightNode.childNodes().at(1).firstChild().firstChild();

                QDomNode operatorNode=opcallNode.firstChild();

                QDomNode sizeNode=opcallNode.childNodes().at(1);

                if(sizeNode.toElement().tagName()=="size")
                {
                    sizeNode.replaceChild(node.cloneNode(true),sizeNode.firstChild());
                    equation.isParaHigh=false;
                }

                if(sizeNode.toElement().tagName()=="instanceParameters")
                {
                    opcallParaOperator newParaOperator;

                    newParaOperator.paraValue=opcall.paraValue;

                    newParaOperator.operatorName=operatorNode.firstChild().toElement().attribute("name");

                    QDomElement newOperatorRef=operatorNode.firstChild().cloneNode(true).toElement();

                    newOperatorRef.setAttribute("name",newParaOperator.operatorName+"_"+newParaOperator.paraValue.value);

                    operatorNode.replaceChild(newOperatorRef,operatorNode.firstChild());

                    opcallNode.removeChild(sizeNode);

                    equation.isParaHigh=false;

                    paraOperatorList.append(newParaOperator);

                    //修改页面文件中的OpeName
                    for(int i=0;i<data.diagrams.size();i++)
                    {
                        Diagram dia=data.diagrams.at(i);

                        for(int i=0;i<dia.equations.size();i++)
                        {
                            Equation equation=dia.equations.at(i);

                            if(equation.isParaHigh&&equation.operatorType=="OpCall")
                            {
                                equation.opeName=newParaOperator.operatorName+"_"+newParaOperator.paraValue.value;

                                dia.equations[i]=equation;
                            }
                        }

                        data.diagrams[i]=dia;
                    }

                }

            }

            QDomNodeList equationChild=equationNode.childNodes();
            for(int i=0;i<equationChild.size();i++)
            {
                if(equationChild.at(i).toElement().tagName()=="oid")
                {
                    equationChild.at(i).toElement().setAttribute("value",QUuid::createUuid().toString(QUuid::WithoutBraces));
                }
            }

            data.equations[i].node=equationNode.cloneNode(true);

        }

        //修改实例化操作符的变量、dia的oid，保持oid的唯一性
        for(auto &item:data.variables)
        {
            item.id=QUuid::createUuid().toString(QUuid::WithoutBraces);
            item.node.namedItem("oid").toElement().setAttribute("value",item.id);
        }

        for(auto &item:data.diagrams)
        {
            QString newDiaOid=QUuid::createUuid().toString(QUuid::WithoutBraces);
            item.redaceOid=newDiaOid;

        }

        OperatorImporter operatorImporter;
        operatorImporter.m_operator=data;
        operatorImporter.saveOperatorFile(redaceProjectPath,scadeProjectName,operatorImporter.m_operator.operatorFileName,operatorImporter.m_operator);
        operatorImporter.saveDiagramFile(redaceProjectPath+"/"+scadeProjectName,operatorImporter.m_operator);

        //修改rpf文件
        QFile file(redaceProjectPath+"/"+scadeProjectName+"/"+scadeProjectName+".rpf");

        QString strAll;
        QStringList strList;

        if(file.open(QIODevice::ReadOnly|QIODevice::Text))
        {
            QTextStream stream(&file);
            stream.setCodec("UTF-8");
            strAll=stream.readAll();
        }

        file.close();

        if(file.open(QIODevice::WriteOnly|QIODevice::Text))
        {
            QTextStream stream(&file);
            stream.setCodec("utf-8");
            strList=strAll.split("\n");

            for(int i=0;i<strList.size();i++)
            {
                stream<<strList.at(i)<<endl;

                if(strList.at(i).contains("foldertype=\"operator\""))
                {
                    stream<<"<FileRef id=\"0\" CRC=\"\" Name=\""+data.operatorName+"\" Path=\".\\"+data.operatorFileName+"\"/>"<<endl;
                }
            }
        }

    }
}

//判断库工程中的操作符与现有的操作符是否存在命名冲突
bool isOperatorNameConflict(QString operatorName,QList<Operator> operators)
{
    bool index=false;
    for(int i=0;i< operators.size();i++)
    {
        if(operatorName== operators.at(i).operatorName)
        {
            index=true;
            break;
        }
    }
    if(index==true)
    {
        return true;
    }
    else {
        return false;
    }
}

void getLibProject(QString projectPath,P_SCADEProInfo projectInfo)
{
    ProjectInfoImport proInfoImporter;//工程信息导入模块
    proInfoImporter.proInfoParse(projectPath,&proInfoImporter.sProInfo);

    for(int i=0;i<proInfoImporter.sProInfo.projectLibsName.size();i++)
    {
        bool index=false;
        for(int j=0;j<projectInfo->projectLibsName.size();j++)
        {

            if(QFileInfo(projectInfo->projectLibsName.at(j)).fileName()==QFileInfo(proInfoImporter.sProInfo.projectLibsName.at(i)).fileName())
            {
                index=true;
            }
        }

        if(index==false)
        {
            projectInfo->projectLibsName.append(proInfoImporter.sProInfo.projectLibsName.at(i));
            projectInfo->logList.append(proInfoImporter.sProInfo.logList);
            getLibProject(proInfoImporter.sProInfo.projectLibsName.at(i),projectInfo);
        }

    }
}

void MainWindow::on_pushButton_clicked()
{
    //选择SCADE工程
    QString scadeProjectFilePath=QFileDialog::getOpenFileName(this,"选择SCADE工程",QDir::currentPath(),"SCADE工程文件(*.etp)");
    if(!scadeProjectFilePath.isEmpty())
        ui->lineEdit->setText(scadeProjectFilePath);
}

void MainWindow::on_pushButton_2_clicked()
{
    //选择REDACE工程位置
    QString redaceProjectPath=QFileDialog::getExistingDirectory(this,"选择MODEN工程位置",QDir::currentPath());
    if(!redaceProjectPath.isEmpty())
        ui->lineEdit_2->setText(redaceProjectPath);
}

void MainWindow::on_pushButton_3_clicked()
{    
    QString scadeProjectFilePath=ui->lineEdit->text();//获取SCADE工程文件路径
    QString scadeProjectName=QFileInfo(scadeProjectFilePath).baseName();//获取SCADE工程名
    QString scadeProjectDir=QFileInfo(scadeProjectFilePath).absolutePath();//获取SCADE工程绝对路径
    QString redaceProjectPath=ui->lineEdit_2->text();//获取REDACE工程路径

    //导入前检查，检查导入的SCADE工程和生成文件夹合法性
    if(!checkBeforeImporte(scadeProjectFilePath,scadeProjectName,redaceProjectPath))
    {
        return;
    }

    //生成导入报告文件
    QFile reportFile(redaceProjectPath+"/"+scadeProjectName+"/"+scadeProjectName+".txt");
    if( reportFile.open(QIODevice::WriteOnly | QIODevice::Text) )
    {
        QTextStream out(&reportFile);

        out<<QString(scadeProjectName+"导入报告:")<<endl;

        out<<endl;

        reportFile.close();
    }

    ProjectInfoImport proInfoImporter;//工程信息导入模块
    proInfoImporter.proInfoParse(scadeProjectFilePath,&proInfoImporter.sProInfo);//解析SCADE工程工程信息

    for(int i=0;i<proInfoImporter.sProInfo.projectLibsName.size();i++)
    {
        getLibProject(proInfoImporter.sProInfo.projectLibsName.at(i),&proInfoImporter.sProInfo);
    }

    ProjectInfoImport proInfoImporter1;
    for(int i=0;i<proInfoImporter.sProInfo.projectLibsName.size();i++)
    {
        proInfoImporter1.proInfoParse(proInfoImporter.sProInfo.projectLibsName.at(i),&proInfoImporter1.sProInfo);
        proInfoImporter.sProInfo.projectLib.append(proInfoImporter1.sProInfo);        

        for(int i=0;i<proInfoImporter1.sProInfo.opeartors.size();i++)
        {
            if(!isOperatorNameConflict(proInfoImporter1.sProInfo.opeartors.at(i).operatorName,proInfoImporter.sProInfo.opeartors))
            {
                proInfoImporter.sProInfo.opeartors.append(proInfoImporter1.sProInfo.opeartors.at(i));
            }
        }

    }
    //proInfoImporter.logList.append(proInfoImporter1.logList);
    //proInfoImporter.sProInfo.typeList.append(proInfoImporter.sProInfo.typeList);

    proInfoImporter.proInfoProcess(reportFile);//工程信息处理
    proInfoImporter.generateSolutionFile(redaceProjectPath,scadeProjectName);//生成解决方案文件
    proInfoImporter.generateProjectFile(redaceProjectPath,scadeProjectName);//生成工程文件

    QString version=proInfoImporter.sProInfo.version;//SCADE工程版本

    if(!proInfoImporter.sProInfo.logList.isEmpty())
    {
        if( reportFile.open(QIODevice::Append | QIODevice::Text) )
        {
            QTextStream out(&reportFile);

            //out<<operatorImporter.m_operator.operatorName+":"<<endl;

            for(int i=0;i<proInfoImporter.sProInfo.logList.size();i++)
            {
                out<<proInfoImporter.sProInfo.logList.at(i)<<endl;
            }

            out<<endl;

            reportFile.close();

        }

    }

    //生成空的Constant.xml文件，防止scade工程中无默认模型文件和包文件导致无常量文件生成
    generateEmptyConstantFile(redaceProjectPath+"/"+scadeProjectName+"/Constant.xml");

    TypeImport typeImporter;//数据类型导入模块

    //默认模型文件
    if(!proInfoImporter.sProInfo.defaultFile.isEmpty())
    {

        ConstantImport constantImporter;//常量导入模块

        QFile file(proInfoImporter.sProInfo.defaultFile);
        if(!file.open(QFile::ReadOnly))
            return;

        QDomDocument doc;

        if(!doc.setContent(&file))
        {
            file.close();
            return;
        }
        file.close();

        QDomElement root=doc.documentElement();

        typeImporter.getTypeList(root);
        typeImporter.saveTypeList(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml",typeImporter.m_datas);

        constantImporter.constantImport(redaceProjectPath+"/"+scadeProjectName+"/Constant.xml",root);
    }

    //package文件
    for(int i=0;i<proInfoImporter.sProInfo.packages.size();i++)
    {
        TypeImport typeImporter;

        ConstantImport constantImporter;

        typeImporter.getTypeList(proInfoImporter.sProInfo.packages.at(i).packageNode);
        typeImporter.saveTypeList(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml",typeImporter.m_datas);

        constantImporter.constantImport(redaceProjectPath+"/"+scadeProjectName+"/Constant.xml",proInfoImporter.sProInfo.packages.at(i).packageNode);
    }

    //子项目
    for(int i=0;i<proInfoImporter.sProInfo.projectLib.size();i++)
    {
        SCADEProInfo sProInfo=proInfoImporter.sProInfo.projectLib.at(i);
        //默认模型文件
        if(!sProInfo.defaultFile.isEmpty())
        {
            ConstantImport constantImporter;//常量导入模块

            QFile file(sProInfo.defaultFile);
            if(!file.open(QFile::ReadOnly))
                return;

            QDomDocument doc;

            if(!doc.setContent(&file))
            {
                file.close();
                return;
            }
            file.close();

            QDomElement root=doc.documentElement();

            typeImporter.getTypeList(root);
            typeImporter.saveTypeList(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml",typeImporter.m_datas);

            constantImporter.constantImport(redaceProjectPath+"/"+scadeProjectName+"/Constant.xml",root);
        }

        //package文件
        for(int i=0;i<sProInfo.packages.size();i++)
        {
            TypeImport typeImporter;

            ConstantImport constantImporter;

            typeImporter.getTypeList(sProInfo.packages.at(i).packageNode);
            typeImporter.saveTypeList(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml",typeImporter.m_datas);

            constantImporter.constantImport(redaceProjectPath+"/"+scadeProjectName+"/Constant.xml",sProInfo.packages.at(i).packageNode);
        }
    }

    //        for(int j = 0; j < proInfoImporter1.sProInfo.typeList.size(); j++){
    //            qDebug()<<proInfoImporter1.sProInfo.typeList.at(j).toElement().attribute("name");
    //        }

    typeImporter.saveTypeList(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml", proInfoImporter.sProInfo.typeList);
    typeImporter.saveTypeList(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml", proInfoImporter1.sProInfo.typeList);

    //数据类型的导入报告
    if(!typeImporter.logList.isEmpty())
    {
        if( reportFile.open(QIODevice::Append | QIODevice::Text) )
        {
            QTextStream out(&reportFile);

            //out<<operatorImporter.m_operator.operatorName+":"<<endl;

            for(int i=0;i<typeImporter.logList.size();i++)
            {
                out<<typeImporter.logList.at(i)<<endl;
            }

            out<<endl;

            reportFile.close();

        }
    }

    //增加int_signal、bool_signal、device_signal、real_signal四种数据类型
    DataTypeDefine::DataTypeList datas;

    addSignalTypes(datas);
    typeImporter.saveDataTypeFile(redaceProjectPath+"/"+scadeProjectName+"/TypeData.xml",datas);

    //将默认模型文件中的'\x00'替换为'/x00'
    x00_Process(redaceProjectPath,scadeProjectName);

    //操作符文件
    QList<opcallParaOperator> paraOperatorList;//含参操作符被调用的列表
    QList<opcallOperator> opCallList;//函数调用列表
    QList<opcallParaOperator> tOperatorList;//含泛型操作符被调用的列表
    QList<OperatorData> operatorList;//所有自定义操作符

    for(int i=0;i<proInfoImporter.sProInfo.opeartors.size();i++)
    {
        Operator thisOperator=proInfoImporter.sProInfo.opeartors.at(i);

        OperatorImporter operatorImporter;
        operatorImporter.m_operator.projectOid=proInfoImporter.rProInfo.oid;
        operatorImporter.m_operator.operatorName=thisOperator.operatorName;
        operatorImporter.m_operator.path=thisOperator.path;
        operatorImporter.m_operator.cFilePath=thisOperator.cFilePath;
        operatorImporter.m_operator.operatorFileName=operatorImporter.m_operator.operatorName+".redace";
        operatorImporter.m_operator.projectPath=redaceProjectPath+"/"+scadeProjectName;

        operatorImporter.readOperatorFile(thisOperator.operatorNode);
        operatorImporter.saveOperatorFile(redaceProjectPath,scadeProjectName,operatorImporter.m_operator.operatorFileName,operatorImporter.m_operator);
        operatorImporter.saveDiagramFile(redaceProjectPath+"/"+scadeProjectName,operatorImporter.m_operator);

        //操作符的导入报告
        if(!operatorImporter.m_operator.logList.isEmpty())
        {
            if( reportFile.open(QIODevice::Append | QIODevice::Text) )
            {
                QTextStream out(&reportFile);

                out<<operatorImporter.m_operator.operatorName+":"<<endl;

                for(int i=0;i<operatorImporter.m_operator.logList.size();i++)
                {
                    out<<operatorImporter.m_operator.logList.at(i)<<endl;
                }

                out<<endl;

                reportFile.close();

            }
        }

        paraOperatorList.append(operatorImporter.m_operator.paraOperatorList);
        operatorList.append(operatorImporter.m_operator);

        opCallList.append(operatorImporter.m_operator.opCallList);

    }

    //实例化泛型
    instantiateGenerics(opCallList,operatorList,redaceProjectPath,scadeProjectName);

    //实例化参数
    instantiateParameter(paraOperatorList,operatorList,redaceProjectPath,scadeProjectName);
//    Log::getInstance().log("redaceProjectPath=" + redaceProjectPath + "/" + scadeProjectName);
    qDebug("debug msg");
    clearDir(redaceProjectPath + "/" + scadeProjectName);
    TypeImport::clearDataTypeMap();
    ConstantImport::clearConstantMap();
    QMessageBox::information(this,"提示信息","导入完成");

}

void MainWindow::clearDir(const QString &dirPath)
{
    QStringList fileList;
    QDir dir(dirPath);
    QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::Dirs);
    foreach (auto fileInfo, fileInfoList) {
//        if(fileInfo.isDir())
//        {

//            getFileListUnderDir(fileInfo.absoluteFilePath());
//        }

        if(fileInfo.isFile() && fileInfo.suffix() == "redace")
        {
            clearXMLFile(fileInfo.absoluteFilePath());
        }
    }
}

void MainWindow::clearXMLFile(const QString &filepath)
{
    QFile file(filepath);
    if(!file.open(QFile::ReadOnly|QFile::Text))
        return;

    QStringList list;
    while(!file.atEnd()){
        QByteArray bytes = file.readLine();
        QString line(bytes);
        if(line.contains("<!--"))
            continue;
        if(line.contains("::")){
            QStringList l = line.split("::");
            QString firstPart = l.at(0);
            QString lastPart = l.at(l.size()-1);
            int index = firstPart.lastIndexOf("\"");
            QString tmp = firstPart.mid(0, index + 1);
            QString newline = tmp + lastPart;
            line = newline;
        }
        if(line.contains("\"<")){
            line.replace("\"<", "\"&lt;");
        }
        if(line.contains(">\"")){
            line.replace(">\"", "&gt;\"");
        }
        list.append(line);
    }
    file.close();

    if(file.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate))
    {
        QTextStream writeStream(&file);
        for(int i = 0; i < list.size(); i++){
//            qDebug()<<list.at(i);
            writeStream<<list.at(i);
        }
        file.close();
    }
}

